package com.new4net.exe_stream.instruction.impl;


import com.new4net.common.Triplet;
import com.new4net.common.Tuple;
import com.new4net.exe_stream.meta.ExecutionContext;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;

public class SwitchInstruction<R> extends AbstractInstruction {
    private Triplet<String, Predicate<ExecutionContext.InstructionContext>,Function<ExecutionContext.InstructionContext,R>> ifContent;

    public List<String> getAllBranchName(){
        List<String> result = new ArrayList<>();
        if(ifContent!=null){
            result.add(ifContent.getT1());
        }
        elseIfContents.forEach(t->{
            result.add(t.getT1());
        });

        if(elseContent!=null){
            result.add(elseContent.getT1());
        }
        return result;

    }

    public SwitchInstruction(String instructionName) {
        super(instructionName);
        this.instructionName = instructionName;
    }

    public void setIfContent(String title, Predicate<ExecutionContext.InstructionContext> predicate, Function<ExecutionContext.InstructionContext,R> fun) {
        this.ifContent = new Triplet<>(title,predicate,fun);
    }

    private List<Triplet<String, Predicate<ExecutionContext.InstructionContext>,Function<ExecutionContext.InstructionContext,R>>> elseIfContents=new ArrayList<>();

    public void addElseIfContent(String title, Predicate<ExecutionContext.InstructionContext> predicate, Function<ExecutionContext.InstructionContext,R> fun){
        elseIfContents.add( new Triplet<>(title,predicate,fun));
    }

    private Tuple<String,Function<ExecutionContext.InstructionContext,R>> elseContent;

    public void setElseContent(String title, Function<ExecutionContext.InstructionContext,R> fun) {
        this.elseContent = new Tuple<>(title,fun);
    }





    @Override
    protected void exe() {
        if(ifContent!=null){
            String stepName = ifContent.getT1();

            boolean flag =  ifContent.getT2().test(instructionContext);
            if(flag){
                step(stepName);
                retVal= ifContent.getT3().apply(instructionContext);
                return;
            }
        }

        if(!elseIfContents.isEmpty()){
            for(int i=0;i<elseIfContents.size();i++){
                Triplet<String, Predicate<ExecutionContext.InstructionContext>, Function<ExecutionContext.InstructionContext, R>> content = elseIfContents.get(i);
                if(content!=null){
                   String stepName = content.getT1();

                  boolean  flag =  content.getT2().test(instructionContext);
                    if(flag){
                        step(stepName);
                        retVal= content.getT3().apply(instructionContext);
                        return;
                    }

                }

            }
        }
        if(elseContent!=null){
            String stepName = elseContent.getT1();

            step(stepName);
            retVal= elseContent.getT2().apply(instructionContext);
            return;
        }
        retVal=null;


    }

    @Override
    public String getInstuctionType() {
        return "switch";
    }
}
